#ifndef FUENTE_H
#define FUENTE_H
#include <QImage>
#include <QVector>
#include "math.h"
#include <iostream>
#include <fstream>
#include "nodoarbol.h"

#define CANT_COLORES 256

using namespace std;

//En esta clase vamos a desarrollar los algortimos.
class Fuente
{
private:
    QImage image;
    QImage imagen2;
    double probColor[256];

    int extOrden;//entero que dice de que orden es la extension que tiene la fuente en el momento

    //matriz con todas las probabilidades condicionales: prob de que el color j venga despues de i
    double markov[256][256];

    //esta lista almacena la probabilidad de cada color.
    QList<NodoArbol> *proba;

    QList<NodoArbol> *colores;
    NodoArbol arbolHuffman;

    //Esta lista almacena el simbolo,junto con su codigo asociado
    QVector< QList< NodoArbol> > codigo;

    //arma el arbol de huffman, es decir cada hoja es un simbolo. y el camino a ella el codigo a la derecha 0. izquierda 1.
    NodoArbol huffmanTree(QList<NodoArbol>* );

    // genera el codigo, y lo almacena en una lista de lista. la primera lista obtiene la cantidad de simbolos y la segunda su
    //codigo asociado
    void codeGenerate (NodoArbol* ,QList<NodoArbol>*,int );

    //ordena la lista en forma decreciente
    QList<NodoArbol>* ordenarLista(QList<NodoArbol>* );

    //dado el simbolo recorre la lista de lista y obtiene el codigo asociado
    QList<NodoArbol> getCodigo(QString simbolo);
    FILE *archivo;
    void matMarkov(int[CANT_COLORES][CANT_COLORES]);
    void calcularProbabilidades(double[], int[CANT_COLORES][CANT_COLORES], double);
    void cargarFrecuencias(double[], int[CANT_COLORES][CANT_COLORES], int, int);
    void limpiarLista(QList<NodoArbol> *);
    QList<NodoArbol> *clonar(QList<NodoArbol> *);

    int getSigPixel(int &, int &);
    QString getSimbolo(QList<int>);

    //funcion auxiliar para calc entropiaM. Genera una lista de probabilidades a partir de la matriz.
    void probaDadoI(double[CANT_COLORES],int);
    void writeFile(int);
    void fileOpen(char*);
    void fileClose();
    void putPixel(int &x,int& y,int s);
    void huffman();
    double entropiaMAT(int);


public:
    void codecSource(char*);
    Fuente(QImage i);
    Fuente();
    void setImage(QImage i);
    void setExtOrden(int eo);
    int getExtOrden();
    Fuente decodecHuffman();
    QImage getFuente();
    int getColor(int, int);
    int getSizeProba();
    void cargarProbabilidades();
    void extender(int);
    void guardarExt(char*);
    void decodec(char*);
    QImage getImagen();

    void getSim(QList<bool>*,NodoArbol*, int&);
    double entropia();
    double entropia1();
    double entropiaN(int);

    double mediaLong();

    double getProb(int);
    QList<NodoArbol>* getProbabilidades();



};

#endif // FUENTE_H
